﻿using ICMS.PluginInterfaces;
using SharpCompress.Archive;
using SharpCompress.Common;
using SharpCompress.Reader;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows.Forms;

namespace commonImportPlugin.Common
{
    public class GetFileUtil
    {
        //
        //  两种筛选文件的方式（文件名正则和文件内容正则筛选数据)
        //  
        #region 
        /// <summary>
        /// 根据文件名正则或文件名内容正则过滤文件
        /// </summary>
        /// <param name="allfiles">待过滤的文件list</param>
        /// <param name="_nameOrContentRegexs">
        /// 格式：文件名正则[#]文件内容正则
        /// 注多个文件名正则用‘|’拼接
        /// </param>
        /// <param name="contentMode">
        /// 文件内容模式;
        /// contentMode='byte'表示byte字节格式。
        /// 其他表示转码后格式
        /// </param>
        /// <returns></returns>
        public List<string> FilterFilesWithNameOrContentRegexs(List<string> allfiles, string _nameOrContentRegexs, string contentMode)
        {
            List<string> results = new List<string>();

            //获取参数
            FilterParameter filterParameter = GetFilterParameter(_nameOrContentRegexs);

            //先根据文件名正则筛选
            List<string> afterFilterNameList = FilterFilesWithNameRegexs(allfiles, filterParameter.nameRegexs);

            //根据内容正则筛选
            if (filterParameter.contentRegexs != null)
            {
                //筛选
                results = FilterFilesWithContentRegexs(afterFilterNameList, filterParameter.contentRegexs, contentMode);
            }
            else
                results = afterFilterNameList;

            return results;
        }
            
        ////////////////////////////根据文件名正则筛选数据////////////////
        /// <summary>
        /// 根据文件的正则表达式来筛选文件
        /// </summary>
        /// <param name="allfiles">文件list</param>
        /// <param name="filterFileRegexs">筛选的文件扩张名2个以上用‘|’割开</param>
        /// <returns>返回的文件list</returns>
        private List<string> FilterFilesWithNameRegexs(List<string> allfiles, string _nameRegexs)
        {
            List<string> finalFiles = new List<string>();
            string[] nameRegexs = _nameRegexs.ToLower().Split('|');
            finalFiles = allfiles.FindAll(delegate(string file)
            {
                //获取文件
                if (nameRegexs.Contains(".*"))//存在.*则获取所有文件
                {
                    return true;
                }
                else if (nameRegexs.Contains(Path.GetExtension(file).ToLower()))
                {
                    return true;
                }
                else //根据正则表达式获取
                {
                    string fileName = Path.GetFileName(file).ToLower();

                    foreach (string regex in nameRegexs)
                    {
                        if (regex!="" && Regex.IsMatch(fileName, regex))
                        {
                            return true;
                        }
                    }
                }
                return false;
            });

            return finalFiles;
        }

        /////////////////////////根据文件名内容正则筛选数据//////////////
        /// <summary>
        /// 根据文件的内容格式来筛选文件
        /// </summary>
        /// <param name="allfiles">待筛选的文件list</param>
        /// <param name="_contentRegexs">筛选文件内容的正则</param>
        /// <param name="contentMode">文件内容格式
        /// (mode="byte"表示匹配的内容为byte字节内容，其他表示转码后的内容)
        /// </param>
        /// <returns>经过筛选后的list</returns>
        private List<string> FilterFilesWithContentRegexs(List<string> allfiles, string _contentRegexs, string contentMode)
        {
            List<string> afterFilterFiles = new List<string>();//经过筛选后的
            string content = null;//文件内容
            byte[] buffer = new byte[2000]; //缓存     
            FileStream fs = null;
            long readCounts = 2000;//获取前多少字节

            foreach (string file in allfiles)
            {
                fs = File.OpenRead(file);

                if (fs != null)
                {
                    long counts = fs.Length > readCounts ? readCounts : fs.Length;
                    fs.Read(buffer, 0, (int)counts);

                    if (contentMode != null && contentMode.Trim() == "byte")//模式一
                    {
                        content = BitConverter.ToString(buffer).Replace("-", "");
                    }
                    else//模式二
                    {
                        content = Encoding.GetEncoding("GB2312").GetString(buffer).Replace("-", "");
                    }

                    if (Regex.IsMatch(content, _contentRegexs))
                    {
                        afterFilterFiles.Add(file);
                    }
                }
                fs.Close();
            }

            return afterFilterFiles;
        }
        /////////////////////////获取筛选参数///////////////////////////
        #region 获取筛选参数
        /// <summary>
        /// 获取筛选参数的参数类
        /// </summary>
        public class FilterParameter
        {
            /// <summary>
            /// 筛选文件名的正则
            /// </summary>
            public string nameRegexs { set; get; }
            /// <summary>
            /// 筛选文件内容的正则
            /// </summary>
            public string contentRegexs { set; get; }
        }
        /// <summary>
        /// 获取筛选的参数
        /// </summary>
        /// <param name="_nameOrContentRegexs">string筛选的参数</param>
        /// <returns>参数</returns>
        private FilterParameter GetFilterParameter(string _nameOrContentRegexs)
        {
            string[] seperaters = new string[] { "[#]" };//分隔符

            FilterParameter parameter = new FilterParameter();

            string[] nameOrContentRegexs = _nameOrContentRegexs.Split(seperaters, StringSplitOptions.None);

            parameter.nameRegexs = nameOrContentRegexs[0];
            if (nameOrContentRegexs.Length == 2)
            {
                parameter.contentRegexs = nameOrContentRegexs[1].Trim();
            }

            return parameter;
        }

        #endregion

        #endregion

        //
        //  解压函数(解压函数  UnRAR UnZip decompressingFile)
        //
        #region 
        /// <summary>
        /// 解压文件（支持zip tar rar三种）
        /// </summary>
        /// <param name="path">解压后存放的路径</param>
        /// <param name="rarPath">解压的解压文件</param>
        public bool DecompressingFile(string afterDecompressionPath, string rarPath)
        {
            string fileExtensionName = Path.GetExtension(rarPath).ToLower();
            try
            {
                if (fileExtensionName == ".zip" || fileExtensionName == ".rar" || fileExtensionName == ".tar")
                {
                    switch (fileExtensionName)
                    {
                        case ".zip":
                        case ".tar":
                            this.UnZip(afterDecompressionPath, rarPath);
                            break;
                        case ".rar":
                            this.UnRAR(afterDecompressionPath, rarPath);
                            break;
                        default:
                            break;
                    }
                }
                return true;
            }
            catch (Exception)
            {
                MessageBox.Show(Path.GetFileName(rarPath) + "该文件解压失败！");
                return false;
            }
        }
        ////////////////解压 UnZip/////////////////////
        /// <summary>
        /// 解zip
        /// </summary>
        /// <param name="path">解压后存放的路径</param>
        /// <param name="rarPath">所需解压的解压文件</param>
        private void UnZip(string path, string rarPath)
        {
            IArchive archive = ArchiveFactory.Open(rarPath);
            try
            {
                foreach (var entry in archive.Entries)
                {
                    if (!entry.IsDirectory)
                    {
                        entry.WriteToDirectory(path, ExtractOptions.ExtractFullPath | ExtractOptions.Overwrite);
                    }
                }
                archive.Dispose();
            }
            catch
            {
                MessageBox.Show("解压失败！");
                return;
            }

        }
        ////////////// 解压缩 UnRAR///////////////////
        /// <summary>
        /// 解压缩 UnRAR
        /// </summary>
        /// <param name="path">文件解压路径（绝对）</param>
        /// <param name="rarPath">将要解压缩的文件路径（绝对路径）：RAR</param>
        /// <returns>无</returns>
        private void UnRAR(string path, string rarPath)
        {
            using (Stream stream = File.OpenRead(rarPath))
            {
                var reader = ReaderFactory.Open(stream);
                if (Convert.ToString(reader.ArchiveType).ToLower() == "zip")
                    throw new Exception("请不要人为修改压缩包后缀名");
                try
                {
                    while (reader.MoveToNextEntry())
                    {
                        if (!reader.Entry.IsDirectory)
                            reader.WriteEntryToDirectory(path, ExtractOptions.ExtractFullPath | ExtractOptions.Overwrite);
                    }
                }
                catch
                {
                    MessageBox.Show("解压失败！");
                    return;
                }
                stream.Close();
            }
        }
        //////////////////////////////
        #endregion

        //
        //获取目录下所有文件
        //
        #region
        /// <summary>
        /// 获取一个目录下面执行类型的所有文件
        /// </summary>
        /// <param name="fileOrDirectyPath">需要获取文件夹的路径或文件路径</param>
        /// <param name="allFiles">用来存储所有文件的list</param>
        /// <param name="_filterFileRegexs">获取筛选文件的正则表达式</param>
        /// <param name="needClearFoler">需要清除的目录</param>
        /// <returns>true 成功，false失败</returns> public bool getDirectoriesAllFiles(string fileOrDirectyPath, List<string> allFiles, string strFilterExtension, List<string> needClearFoler)
        private bool GetDirectoriesAllFiles(string fileOrDirectyPath, List<string> allFiles, string _filterFileRegexs, List<string> needClearFoler)
        {
            string[] directories = null;
            string[] fileNames = null;
            string[] RARExtensions = { ".zip", ".rar", ".tar" };//压缩包扩展名
            string[] filterFileRegexs = null;
            string afterDecompressionPath = null;

            try
            {
                filterFileRegexs = _filterFileRegexs.ToLower().Split('|');
                #region 获取文件
                if (Directory.Exists(fileOrDirectyPath))
                {
                    directories = Directory.GetDirectories(fileOrDirectyPath);
                    foreach (string dir in directories)
                        GetDirectoriesAllFiles(dir, allFiles, _filterFileRegexs, needClearFoler);//递归

                    fileNames = Directory.GetFiles(fileOrDirectyPath);

                    foreach (string file in fileNames)
                        GetDirectoriesAllFiles(file, allFiles, _filterFileRegexs, needClearFoler);//递归

                }
                else
                {
                    string fileExtensionName = Path.GetExtension(fileOrDirectyPath).ToLower();
                    if (RARExtensions.Contains(fileExtensionName))
                    {
                        afterDecompressionPath = fileOrDirectyPath.Remove(fileOrDirectyPath.LastIndexOf('.'));

                        if (Directory.Exists(afterDecompressionPath))// 删除之前的目录
                            Directory.Delete(afterDecompressionPath, true);

                        if (!DecompressingFile(afterDecompressionPath, fileOrDirectyPath))
                            return false;
                        else
                        {
                            needClearFoler.Add(afterDecompressionPath);
                            GetDirectoriesAllFiles(afterDecompressionPath, allFiles, _filterFileRegexs, needClearFoler);//递归

                        }
                    }

                    //获取文件
                    if (filterFileRegexs.Contains(".*"))//存在.*则获取所有文件
                    {
                        allFiles.Add(fileOrDirectyPath);
                    }
                    else if (filterFileRegexs.Contains(Path.GetExtension(fileOrDirectyPath).ToLower()))
                    {
                        allFiles.Add(fileOrDirectyPath);
                    }
                    else //根据正则表达式获取
                    {
                        string fileName = Path.GetFileName(fileOrDirectyPath).ToLower();

                        foreach (string filterFileRegex in filterFileRegexs)
                        {
                            if (Regex.Match(fileName, filterFileRegex).Success)
                            {
                                allFiles.Add(fileOrDirectyPath);
                                break;
                            }
                        }
                    }
                    //if (filterExtensions.Contains(Path.GetExtension(fileOrDirectyPath).ToLower())||filterExtensions.Contains(".*"))//获取指定类型的文件
                    //    allFiles.Add(fileOrDirectyPath);

                }
                #endregion
            }
            catch (Exception)
            {
                MessageBox.Show("解压所有文件过程中出错");
                return false;
            }
            return true;
        }
        #endregion

        //
        //  获取制卡数据文件
        //
        #region 
        /// <summary>
        /// 获取指定类型的文件
        /// </summary>
        /// <param name="folder">目录路径</param>
        /// <param name="filePaths">所选的文件路径数组</param>
        /// <param name="fileExtensions">所需获取文件扩展名(.txt|.bat）.*表示获取所有类型</param>
        /// <param name="outAllFiles">获取到的文件</param>
        ///  <param name="outNeedRemoveFoler">操作完需要删除的目录</param>
        /// <returns>true 成功,false失败</returns>
        public bool GetAllDataFiles(string folder, string[] filePaths, string fileExtensions, out List<string> outAllFiles, out List<string> outNeedRemoveFoler)
        {
            string[] importFiles = filePaths;//非文件夹导入方式获取的文件list  
            List<string> allFiles = new List<string>();//存放获取到的文件
            List<string> needRemoveFoler = new List<string>();//存放需求操作完需要删除的文件路径
            if (folder != null)
                GetDirectoriesAllFiles(folder, allFiles, fileExtensions, needRemoveFoler);
            else
            {
                foreach (string file in importFiles)
                {
                    //获取所有磁条和金融文件
                    GetDirectoriesAllFiles(file, allFiles, fileExtensions, needRemoveFoler);
                }
            }
            outAllFiles = allFiles;
            outNeedRemoveFoler = needRemoveFoler;
            return allFiles.Count == 0 ? false : true;
        }
        #endregion
    }
}
